/*
* parse.hpp - make and destroy parse trees as driven by the parser
*/
#ifndef PARSE_HPP
#define PARSE_HPP

#ifdef _MSC_VER
#pragma once
#endif

#include "jam.hpp"
#include "scan.hpp"
#include "jam_ast.hpp"

///////////////////////////////////////////////////////////////////////////////////////
////// Parse context
///////////////////////////////////////////////////////////////////////////////////////
struct JAMLIB_EXPORT parse_context
{
	scan_context scanner_;
	parse_node_ptr root_;

	parse_context(const jam_string &name,bool debug_mode,bool save_comments) :
		scanner_(name,debug_mode,save_comments){}
	void parse();
};

#define YYPARSE_PARAM context
#define GET_SCANNER (static_cast<parse_context*>(context)->scanner_)
#define YYLEX_PARAM & GET_SCANNER

#define yyerror(err_text) GET_SCANNER.throw_error(err_text,&yylval)

inline int yylex(YYSTYPE *lvalp,void *context)
{
	return static_cast<scan_context*>(context)->yylex(lvalp);
}

inline void parse_save(void *context, parse_node_ptr p)
{
	assert(!static_cast<parse_context*>(context)->root_);
	static_cast<parse_context*>(context)->root_=p;
}

///////////////////////////////////////////////////////////////////////////////////////
////// Node creator
///////////////////////////////////////////////////////////////////////////////////////
inline parse_node_ptr make_node(void *context, parse_node_ptr new_node, 
	const parse_node_ptr &prev_node=parse_node_ptr(),
	const parse_node_ptr &prev_node2=parse_node_ptr())
{
	//TODO: do we really need this??
	if (prev_node)
	{
		new_node->file_=prev_node->file_;

		new_node->line_=prev_node->line_;
		if (prev_node2 && (prev_node2->line_< new_node->line_))
			new_node->line_=prev_node2->line_;				
	} else
		GET_SCANNER.get_input_stream_info(&new_node->file_,&new_node->line_);

	return new_node;
}

inline parse_node_ptr make_node(void *context, parse_node_ptr new_node, 
								const YYSTYPE &symbol)
{
	new_node->file_=symbol.file;
	new_node->line_=symbol.line;	
	return new_node;
}

inline parse_node_ptr make_null_node(void *context, parse_node_ptr new_node)
{
	new_node->file_="";
	new_node->line_=0;
	return new_node;
}

#endif //PARSE_HPP
